/* Includes ------------------------------------------------------------------*/
#include "T117_MTS4_I2C.h"/*IIC地址在T117_MTS4_I2C.h文件中定义，当前定义为0x41，ADDR引脚接VDD*/
#include "MY_I2C_DRV.h"
/**-----------------------------------------------------------------------
  * @brief  把16位二进制补码表示的温度输出转换为以摄氏度为单位的温度读数
  * @param  out：有符号的16位二进制温度输出
  * @retval 以摄氏度为单位的浮点温度
-------------------------------------------------------------------------*/
float MY_OutputtoTemp(int16_t out)
{
	return ((float)out/256.0 + 25.0);	
}

/**-----------------------------------------------------------------------
  * @brief  把以摄氏度为单位的浮点温度值转换为16位二进制补码表示的温度值
  * @param  以摄氏度为单位的浮点温度值
  * @retval 有符号的16位二进制温度值
-------------------------------------------------------------------------*/
int16_t MY_TemptoOutput(float Temp)
{
	return (int16_t)((Temp-25.0)*256.0);
}

/**-----------------------------------------------------------------------
  * @brief  启动温度测量
  * @param  无
  * @retval I2C发送状态
-------------------------------------------------------------------------*/
int MY_ConvertTemp(void)
{	 
	/*主发送16位命令，从以ACK响应命令的最后字节*/
	if(T117I2C_Transmit(I2C_ADDR, Temp_Cmd, SINGLE_CONVERT) != GPIOI2C_XFER_LASTACK)
	{
		return 0;
	}	
	return 1;
}

/**-----------------------------------------------------------------------
  * @brief  等待转换结束后读测量结果
  * @param  iTemp：返回的16位温度测量结果
  * @retval I2C接收状态
-------------------------------------------------------------------------*/
int MY_ReadTempWaiting(uint16_t *iTemp)
{
	uint8_t data[3];
	/*读3个字节。前两个是温度转换结果，最后字节是前两个的校验和--CRC。*/	
	if(T117I2C_Receive(I2C_ADDR,  Temp_lsb, &data[0]) != GPIOI2C_XFER_LASTNACK)
	{		
		return 0;  /*I2C地址头应答为NACK*/
	}
	if(T117I2C_Receive(I2C_ADDR,  Temp_msb, &data[1]) != GPIOI2C_XFER_LASTNACK)
	{		
		return 0;  /*I2C地址头应答为NACK*/
	}
	if(T117I2C_Receive(I2C_ADDR,  Crc_temp, &data[2]) != GPIOI2C_XFER_LASTNACK)
	{		
		return 0;  /*I2C地址头应答为NACK*/
	}
	/*计算接收的前两个字节的校验和，并与接收的第3个CRC字节比较。*/	
	if(data[2] != MY_CRC8(data, 2))
	{
		PR("CRC ERROR,%X,%X,%X\r\n",data[0],data[1],data[2]);
		return 0;  /*CRC验证失败*/
	}		
	*iTemp=(uint16_t)data[1]<<8 | data[0];
	return 1;
}

/**-----------------------------------------------------------------------
  * @brief  修改ALERT引脚用作温度转换完成标志，测温，查询是否转换结束，然后读测量结果
  * @param  iTemp：返回的16温度测量结果
  * @retval I2C接收状态
-------------------------------------------------------------------------*/
int MY_GetTempPolling(uint16_t *iTemp)
{ 
	uint8_t Alert,status=0;

	if(T117I2C_Receive(I2C_ADDR,  Alert_Mode,&Alert) != GPIOI2C_XFER_LASTNACK)
	{		
		return 0;  /*I2C地址头应答为NACK*/
	}	
	 Alert|= CONVERT_FINI;
	if(T117I2C_Transmit(I2C_ADDR, Alert_Mode,Alert) != GPIOI2C_XFER_LASTACK)
	{
		return 0;
	}
	MY_ConvertTemp();
	T117I2C_Receive(I2C_ADDR, Status, &status);
	while((status&0x20)== 0x20)
	{
		MY_DELAY_US(500);
		T117I2C_Receive(I2C_ADDR, Status,&status);
	}
	MY_ReadTempWaiting(iTemp);

	return 1;
}



/**-----------------------------------------------------------------------
  * @brief  单点设置周期测量频率、平均次数和低功耗模式	
  * @param  mps：要设置的周期测量频率（每秒测量次数），可能为下列其一
	*				@arg FRE_8times		：每执行ConvertTemp一次，启动每秒8次重复测量
	*				@arg FRE_4times		：每执行ConvertTemp一次，启动每秒4次重复测量
	*				@arg FRE_2times		：每执行ConvertTemp一次，启动每秒2次重复测量
	*				@arg FRE_1times   ：每执行ConvertTemp一次，启动每秒1次温度测量
	*				@arg FRE_2s		   	：每执行ConvertTemp一次，启动每2秒1次重复测量
	*				@arg FRE_4s		   	：每执行ConvertTemp一次，启动每4秒1次重复测量			
	*				@arg FRE_8s				：每执行ConvertTemp一次，启动每8秒1次重复测量
	*				@arg FRE_16s      ：每执行ConvertTemp一次，启动每16秒1次重复测量
  * @param  avg：要设置的平均次数，可能为下列其一
	*				@arg AVG_1				：平均次数1次
	*				@arg AVG_8		    ：平均次数8次
	*				@arg AVG_16			  ：平均次数16次
	*				@arg AVG_32			  ：平均次数32次
  * @param  sleep：要设置的低功耗模式，可能为下列其一
	*				@arg OFF_PD       ：位清0，不进入低功耗模式
	*				@arg ON_PD        ：进入低功耗模式
  * @retval 无
-------------------------------------------------------------------------*/
int MY_SetCfg(uint8_t Mps, uint8_t avg, uint8_t sleep)
{
    uint8_t cfg;
    if(sleep==OFF_PD)
    {
        cfg=(Mps | avg) & OFF_PD;
    }
    else
    {
        cfg=Mps | avg | OFF_PD;
    }
	if(T117I2C_Transmit(I2C_ADDR, Temp_Cfg,cfg)!= GPIOI2C_XFER_LASTACK)
	{
		return 0;	
	}
	return 1;	
}

/**-----------------------------------------------------------------------
  * @brief  读状态和配置
  * @param  status 返回的状态寄存器值
  * @param  cfg 返回的配置寄存器值
  * @retval 无
-------------------------------------------------------------------------*/
void MY_ReadStatusConfig(uint8_t *status, uint8_t *cfg)
{ 
	T117I2C_Receive(I2C_ADDR,  Status,status);
	T117I2C_Receive(I2C_ADDR,  Temp_Cfg,cfg);
}

/**-----------------------------------------------------------------------
  * @brief  设置报警门限
  * @param  tha_set 要设置的报警高限温度值，单位为摄氏度
  * @param  tla_set 要设置的报警低限温度值，单位为摄氏度
  * @retval 无
-------------------------------------------------------------------------*/
void MY_SetTempAlert(uint16_t tha_set, uint16_t tla_set)
{
	uint8_t hs_m,hs_l,ls_m,ls_l; uint8_t Mode;
	
	hs_m=tha_set>>8;
	hs_l=tha_set& 0xFF;

	ls_m=tla_set>>8;
	ls_l=tla_set& 0xFF;

	T117I2C_Receive(I2C_ADDR,  Alert_Mode,&Mode);
	Mode=Mode&OFF_ALERT;
	T117I2C_Transmit(I2C_ADDR, Alert_Mode,Mode);	
	T117I2C_Transmit(I2C_ADDR, Th_lsb,hs_l);
	T117I2C_Transmit(I2C_ADDR, Th_msb,hs_m);
	T117I2C_Transmit(I2C_ADDR, Tl_lsb,ls_l);
	T117I2C_Transmit(I2C_ADDR, Tl_msb,ls_m);
}

/**-----------------------------------------------------------------------
  * @brief  读报警限
  * @param  tha_set 返回的报警高限温度值，单位为摄氏度
  * @param  tla_set 返回的报警低限温度值，单位为摄氏度
  * @retval 无
-------------------------------------------------------------------------*/
void MY_GetTempAlert(float *tha_set, float *tla_set)
{ 
	uint16_t hs, ls; 
	uint8_t hs_m,hs_l,ls_m,ls_l, Mode;
	T117I2C_Receive(I2C_ADDR,  Alert_Mode,&Mode);
	T117I2C_Receive(I2C_ADDR, Th_lsb,&hs_l);
	T117I2C_Receive(I2C_ADDR, Th_msb,&hs_m);
	T117I2C_Receive(I2C_ADDR, Tl_lsb,&ls_l);
	T117I2C_Receive(I2C_ADDR, Tl_msb,&ls_m);

	hs =( (uint16_t)hs_m<< 8) | hs_l;
	*tha_set = MY_OutputtoTemp((int16_t)hs);
	ls = ((uint16_t)ls_m<< 8 )| ls_l;
	*tla_set = MY_OutputtoTemp((int16_t)ls);			

}

/**-----------------------------------------------------------------------
  * @brief  保存配置寄存器和报警高限、报警低限的内容到E2PROM
  * @param  无
  * @retval 是否成功状态
-------------------------------------------------------------------------*/
int MY_SavetoE2prom(void)
{
	
	if(T117I2C_Transmit(I2C_ADDR, EE_Cmd,EE_COPY)!= GPIOI2C_XFER_LASTNACK)
	{		
		return 0;  /*I2C地址头应答为NACK*/
	}	
	/*等待擦除和编程完成*/		
	MY_DELAY_MS(50);	

  return 1;	
}

/**-----------------------------------------------------------------------
  * @brief  读取芯片ID
  * @param  ID 芯片ID
  * @retval 无
-------------------------------------------------------------------------*/
int MY_ReadID(uint8_t *ID)
{
	T117I2C_Receive(I2C_ADDR, Romcode1,&ID[0]);
	T117I2C_Receive(I2C_ADDR, Romcode2,&ID[1]);
	T117I2C_Receive(I2C_ADDR, Romcode3,&ID[2]);
	T117I2C_Receive(I2C_ADDR, Romcode4,&ID[3]);
	T117I2C_Receive(I2C_ADDR, Romcode5,&ID[4]);
	T117I2C_Receive(I2C_ADDR, Romcode6,&ID[5]);
	T117I2C_Receive(I2C_ADDR, Romcode7,&ID[6]);
	T117I2C_Receive(I2C_ADDR, crc_romcode,&ID[7]);
	return 1;	
}

/**-----------------------------------------------------------------------
  * @brief  读取全部寄存器
  * @param  无
  * @retval 无
-------------------------------------------------------------------------*/
int MY_ReadReg(void)
{
	uint8_t Reg[3], Reg1[9], Reg2[11], Reg3[8],j;
	T117I2C_Receive(I2C_ADDR, 0x00,&Reg[0]);
	T117I2C_Receive(I2C_ADDR, 0x01,&Reg[1]);
	T117I2C_Receive(I2C_ADDR, 0x02,&Reg[2]);

	T117I2C_Receive(I2C_ADDR, 0x03,&Reg1[0]);
	T117I2C_Receive(I2C_ADDR, 0x04,&Reg1[1]);
	T117I2C_Receive(I2C_ADDR, 0x05,&Reg1[2]);
	T117I2C_Receive(I2C_ADDR, 0x06,&Reg1[3]);
	T117I2C_Receive(I2C_ADDR, 0x07,&Reg1[4]);
	T117I2C_Receive(I2C_ADDR, 0x08,&Reg1[5]);
	T117I2C_Receive(I2C_ADDR, 0x09,&Reg1[6]);
	T117I2C_Receive(I2C_ADDR, 0x0A,&Reg1[7]);
	T117I2C_Receive(I2C_ADDR, 0x0B,&Reg1[8]);

	T117I2C_Receive(I2C_ADDR, 0x0C,&Reg2[0]); 
	T117I2C_Receive(I2C_ADDR, 0x0D,&Reg2[1]);
	T117I2C_Receive(I2C_ADDR, 0x0E,&Reg2[2]);
	T117I2C_Receive(I2C_ADDR, 0x0F,&Reg2[3]);
	T117I2C_Receive(I2C_ADDR, 0x10,&Reg2[4]);
	T117I2C_Receive(I2C_ADDR, 0x11,&Reg2[5]);  
	T117I2C_Receive(I2C_ADDR, 0x12,&Reg2[6]);
	T117I2C_Receive(I2C_ADDR, 0x13,&Reg2[7]);
	T117I2C_Receive(I2C_ADDR, 0x14,&Reg2[8]);
	T117I2C_Receive(I2C_ADDR, 0x15,&Reg2[9]);
	T117I2C_Receive(I2C_ADDR, 0x16,&Reg2[10]);

	T117I2C_Receive(I2C_ADDR, 0x18,&Reg3[0]);
	T117I2C_Receive(I2C_ADDR, 0x19,&Reg3[1]);
	T117I2C_Receive(I2C_ADDR, 0x1A,&Reg3[2]);
	T117I2C_Receive(I2C_ADDR, 0x1B,&Reg3[3]);
	T117I2C_Receive(I2C_ADDR, 0x1C,&Reg3[4]); 
	T117I2C_Receive(I2C_ADDR, 0x1D,&Reg3[5]);
	T117I2C_Receive(I2C_ADDR, 0x1E,&Reg3[6]);
	T117I2C_Receive(I2C_ADDR, 0x1F,&Reg3[7]);
	
	PR("\nID:");
	for(j=0;j<8;j++)
	{				
		PR("%2x ",Reg3[j]);	
	}
	PR("\nTemp:");
	for(j=0;j<3;j++)
	{				
		PR(" %2x",Reg[j]);	
	}
	if(Reg[2] != MY_CRC8(Reg, 2))
	{	
		PR("CRC ERROR, %X, %X, %X\r\n",Reg[0],Reg[1],Reg[2]);
	}
	PR("\nScr:");
	for(j=0;j<9;j++)
	{				
		PR(" %2x",Reg1[j]);	
	}
	PR("\nScr_Ext:");
	for(j=0;j<11;j++)
	{				
		PR(" %2x",Reg2[j]);	
	}

  return 1;	
}

/**-----------------------------------------------------------------------
  * @brief  计算多个字节序列的校验和
  * @param  serial：字节数组指针
  * @param  length：字节数组的长度
  * @retval 校验和（CRC）
-------------------------------------------------------------------------*/
#define POLYNOMIAL 	0x131 //100110001
uint8_t MY_CRC8(uint8_t *serial, uint8_t length) 
{
    uint8_t result = 0x00;
    uint8_t pDataBuf;
    uint8_t i;

    while(length--) {
        pDataBuf = *serial++;
        for(i=0; i<8; i++) {
            if((result^(pDataBuf))&0x01) {
                result ^= 0x18;
                result >>= 1;
                result |= 0x80;
            }
            else {
                result >>= 1;
            }
            pDataBuf >>= 1;
        }
    }
		
    return result;
}
